package com.lesso.curry.util;

import com.lesso.curry.exception.SapReflectException;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * 反射工具类
 *
 * @author zqz
 * @since 2023-05-11
 */
public final class ReflectUtils {
    private ReflectUtils() {
    }

    private static final Object[] EMPTY_METHOD_ARGS = new Object[0];

    private static final Class<?>[] EMPTY_TYPES = new Class[0];

    public static Object invoke(Method method, Object obj) {
        return invoke(method, obj, EMPTY_METHOD_ARGS);
    }

    public static Object invoke(Method method, Object obj, Object... args) {
        try {
            return method.invoke(obj, args);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new SapReflectException("执行方法出错，方法名：" + method.getName() + "，类型：" + obj.getClass(), e);
        }
    }

    public static Method findMethod(String methodName, Class<?> clazz) {
        return findMethod(methodName, clazz, EMPTY_TYPES);
    }

    public static Method findMethod(String methodName, Class<?> clazz, Class<?>... parameterTypes) {
        try {
            return clazz.getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            throw new SapReflectException(String.format("未在%s中找到%s(%s)方法", clazz.getName(), methodName, Arrays.toString(parameterTypes)), e);
        }
    }

    public static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null) {
            Collections.addAll(fields, clazz.getDeclaredFields());
            clazz = clazz.getSuperclass();
        }
        return fields;
    }
}
